home *** CD-ROM | disk | FTP | other *** search
- // ------------------------------- //
- // -------- Start of File -------- //
- // ------------------------------- //
- // ----------------------------------------------------------- //
- // C++ Source Code File Name: hexdump.cpp
- // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
- // Produced By: Doug Gaer
- // File Creation Date: 02/13/1996
- // Date Last Modified: 03/17/1999
- // ----------------------------------------------------------- //
- // ------------- Program description and details ------------- //
- // ----------------------------------------------------------- //
- /*
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
- THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
- IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
- YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
- CORRECTION.
-
- This program is used to display the contents of a specified
- file, in both hexadecimal and ASCII, to the console.
- */
- // ----------------------------------------------------------- //
- #include <iostream.h>
- #include <fstream.h>
- #include <ctype.h>
- #include <iomanip.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "hxcrc.h"
-
- // Define this macro for DOS file opens (the default is UNIX)
- // #ifndef __DOS__
- // #define __DOS__
- // #endif
-
- // Hexdump version number and program name
- const double HexdumpVersionNumber = 1031.101;
- const char *ProgramName = "hexdump";
-
- // Program constants
- const int MAX_LINE = 255; // Maximum characters per line
- const int hxBuffSize = 16; // Maximum number of bytes per line
- const int decBuffSize = 8; // Maximum number of bytes per line
-
- // Constants for text parser
- const int MAXWORDLENGTH = 255;
- const int MAXWORDS = 255;
-
- // Program globals
- char in_file[MAX_LINE]; // Input file
- char out_file[MAX_LINE]; // Optional output file name
- int prompting = 0; // Enable prompting during console dump
- int use_console = 1; // Dump to console if no output file is specified
- int decimal_mode = 0; // Display in decimal mode (Default is HEX)
- int building_bin_file = 0; // True if building binary file from text file
- int strip_comments = 0; // True if not adding comments
- int display_crc32 = 0; // True if displaying 32-bit crc checksum
- int display_crc16 = 0; // True if displaying 16-bit crc checksum
- int NumLines = 8; // Default maximum number of lines to display
-
- // Table for HEX to binary conversions
- const char *bintab[16] = {
- "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
- "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
- };
-
- // Program Functions
- void ProcessArgs(int argc, char *argv[]);
- void HelpMessage(const char *program_name, const double version_number);
- int HexFileDump(fstream &infile, ostream &stream);
- int DecFileDump(fstream &infile, ostream &stream);
- void BuildBinaryFile(char *ifname, char *ofname);
- void TruncateLine(char *line, char tline[MAX_LINE], char delimiter1 = '\t',
- char delimiter2 = ';');
- int text_parse(char *string, char words[MAXWORDS][MAXWORDLENGTH],
- int*numwords, char sepchar1 = ' ', char sepchar2 = ' ');
-
- void HelpMessage(const char *program_name, const double version_number)
- {
- char vbuffer[255];
- sprintf(vbuffer, "%.3f", version_number);
- cout << endl;
- cout << "Hexadecimal file dump program version "
- << vbuffer << endl;
- cout << "Usage: " << program_name << " [switches] infile "
- << "outfile (optional)" << endl;
- cout << "Switches: -? = Display this help message." << endl;
- cout << " -c = Display a 32-bit CRC checksum value." << endl;
- cout << " -C = Display a 16-bit CRC checksum value." << endl;
- cout << " -d = Display in decimal mode (Default is HEX)."
- << endl;
- cout << " -p# = Prompting after displaying # line: -p10"
- << endl;
- cout << " -r = Rebuild binary file from hex dump text file.\n"
- << " Only works for files created in hex mode."
- << endl;
- cout << " -s = Strip comments from output." << endl;
- cout << endl;
- cout << " -x = Convert 32-bit HEX number to DEC: -Xfefe"
- << endl;
- cout << " -X = Convert signed 32-bit HEX number to DEC."
- << endl;
- cout << " -B = Convert 32-bit HEX number to binary: -Bfefe"
- << endl;
- cout << " -D = Convert DEC number to HEX: -D23" << endl;
- cout << endl;
- exit(0);
- }
-
- void ProcessArgs(int argc, char *argv[])
- // Process the program's argument list
- {
- int i, ibuf;
- char *sbuf;
- unsigned long ulbuf, bbuf;
- long lbuf;
-
- for(i = 1; i < argc; i++ ) {
- if(*argv[i] == '-') {
- char sw = *(argv[i] +1);
- switch(sw) {
- case '?' :
- HelpMessage(ProgramName, HexdumpVersionNumber);
- break;
-
- case 'c':
- display_crc32 = 1;
- break;
-
- case 'C':
- display_crc16 = 1;
- break;
-
- case 'p' :
- prompting = 1;
- ibuf = atoi(&argv[i][2]);
- if(ibuf > 0) NumLines = ibuf;
- break;
-
- case 'd' :
- decimal_mode = 1;
- break;
-
- case 'r' :
- building_bin_file = 1;
- break;
-
- case 's' :
- strip_comments = 1;
- break;
-
- case 'x' : {
- sbuf = &argv[i][2];
- cout << endl;
- sscanf(sbuf, "%x", &ulbuf);
- cout.setf(ios::uppercase);
- cout << "0x" << hex << ulbuf << " = " << dec << ulbuf << endl;
- cout << endl;
- exit(0);
- break;
- }
-
- case 'X' : {
- sbuf = &argv[i][2];
- cout << endl;
- sscanf(sbuf, "%x", &lbuf);
- cout.setf(ios::uppercase);
- cout << "0x" << hex << lbuf << " = " << dec << lbuf << endl;
- cout << endl;
- exit(0);
- break;
- }
-
- case 'D' : {
- sbuf = &argv[i][2];
- cout << endl;
- sscanf(sbuf, "%u", &ulbuf);
- cout.setf(ios::uppercase);
- cout << ulbuf << " = " << "0x" << hex << ulbuf << endl;
- cout << endl;
- exit(0);
- break;
- }
-
- case 'B' : {
- sbuf = &argv[i][2];
- cout << endl;
- sscanf(sbuf, "%x", &ulbuf);
- cout.setf(ios::uppercase);
- cout << "0x" << hex << ulbuf << " = ";
- bbuf = (ulbuf & 0xf0000000)>>28;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf000000)>>24;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf00000)>>20;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf0000)>>16;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf000)>>12;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf00)>>8;
- cout << bintab[bbuf] << ' ';
- bbuf = (ulbuf & 0xf0)>>4;
- cout << bintab[bbuf] << ' ';
- bbuf = ulbuf & 0x0f;
- cout << bintab[bbuf] << endl;
- cout << endl;
- exit(0);
- break;
- }
-
- default:
- cerr << endl;
- cerr << "Unknown switch " << argv[i] << endl;
- cerr << "Exiting..." << endl;
- cerr << endl;
- exit(0);
- break;
- }
- }
- else {
- strcpy(in_file, argv[i]); // Input file name
- if(argv[i+1]) {
- strcpy(out_file, argv[i+1]); // Output file name
- break;
- }
- else
- break;
- }
- }
- }
-
- int HexFileDump(fstream &infile, ostream &stream)
- {
- register int i, j;
- int count = 0;
- char c[hxBuffSize];
-
- // Print all text in upper case characters
- stream.setf(ios::uppercase);
-
- while(!infile.eof()) {
-
- for(i = 0; i < hxBuffSize && !infile.eof(); i++) {
- infile.get(c[i]);
- }
-
- if(i < hxBuffSize) i--; // Get rid of eof;
-
- for(j = 0; j < i; j++) {
- long xx = (long)c[j];
-
- // Set fill chars and reset first 24 bits for one byte display
- stream << setfill('0') << setw(2) << hex << (xx & 0xFF);
- stream << " "; // Print one space between the bytes
- }
-
- // Set the line spacing to a minimum of bytes per line
- for(; j < hxBuffSize; j++) stream << " "; // Insert 3 spaces
-
- if(!strip_comments) {
- // Separate hex output by one tab and denote comments
- // with a semicolon.
- stream << "\t" << "; ";
-
- // Filter out any non-printable characters
- for(j = 0; j < i; j++)
- if(isgraph(c[j])) stream << c[j];
- else stream << ".";
- }
-
- stream << endl;
-
- if(use_console == 1 && prompting == 1) {
- count++;
- if(count == NumLines) {
- count = 0;
- stream << endl;
- stream << "Press ENTER to continue: ";
- cin.get();
- stream << endl;
- }
- }
- }
-
- infile.close();
-
- return 1;
- }
-
- int DecFileDump(fstream &infile, ostream &stream)
- {
- register int i, j;
- int count = 0;
- char c[decBuffSize];
-
- // Print all text in upper case characters
- stream.setf(ios::uppercase);
-
- while(!infile.eof()) {
-
- for(i = 0; i < decBuffSize && !infile.eof(); i++) {
- infile.get(c[i]);
- }
-
- if(i < decBuffSize) i--; // Get rid of eof;
-
- for(j = 0; j < i; j++) {
- long xx = (long)c[j];
-
- // Set fill chars and reset first 24 bits for one byte display
- stream << setfill('0') << setw(3) << dec << (xx & 0xFF);
- stream << " "; // Print one space between the bytes
- }
-
- // Set the line spacing to a maximum number of bytes per line
- for(; j < decBuffSize; j++) stream << " "; // Insert 4 spaces
-
- if(!strip_comments) {
- // Separate hex output by one tab and denote comments
- // with a semicolon.
- stream << "\t" << "; ";
-
- // Filter out any non-printable characters
- for(j = 0; j < i; j++)
- if(isgraph(c[j])) stream << c[j];
- else stream << ".";
- }
-
- stream << endl;
-
- if(use_console == 1 && prompting == 1) {
- count++;
- if(count == NumLines) {
- count = 0;
- stream << endl;
- stream << "Press ENTER to continue: ";
- cin.get();
- stream << endl;
- }
- }
- }
-
- infile.close();
-
- return 1;
- }
-
- void BuildBinaryFile(char *ifname, char *ofname)
- {
- cout << "Building new binary file from hex dump text file..." << endl;
-
- if(ifname[0] == 0) {
- cout << endl;
- cout << "You must specify a valid hex dump text file." << endl;
- cout << endl;
- exit(0);
- }
-
- // Default output file name if none specified on command line
- if(ofname[0] == 0) ofname = "outfile.bin";
-
- ifstream infile(ifname, ios::in|ios::nocreate);
- if(!infile) {
- cerr << "Could not open " << ifname << endl;
- exit(0);
- }
-
- #if defined(__DOS__)
- // In MS-DOS/Windows there are two file types, text and binary
- fstream outfile(ofname, ios::out|ios::in|ios::trunc|ios::binary);
- // NOTE: There is no ios::in or ios::out default mode for fstream objects.
- // You must specify both modes for read and write files.
- #elif defined(__DJGPP2721__)
- // DJGPP 2.7.2.1 will not create a file using ios::out|ios::in modes
- fstream outfile(ofname, ios::out|ios::binary);
- #else
- // In UNIX there is only one file type
- fstream outfile(ofname, ios::out|ios::in|ios::trunc);
- #endif
-
- if(!outfile) {
- cerr << "Could not create " << ofname << endl;
- exit(0);
- }
-
- char words[MAXWORDS][MAXWORDLENGTH];
- char LineBuffer[MAX_LINE];
- char InputBuffer[MAX_LINE];
- int i, num, byte_count = 0;
- long word_val;
- unsigned char byte_val;
- unsigned long CRC32 = 0xffffffffL;
- unsigned long outfile_CRC32, CRC32_check;
- hxCRC crc;
-
- // Clear the buffers
- for(i = 0; i < MAX_LINE; i++) LineBuffer[i] = '\0';
- for(i = 0; i < MAX_LINE; i++) InputBuffer[i] = '\0';
-
- while(infile) {
- infile.getline(LineBuffer, MAX_LINE);
-
- // Truncate the line when the first tab is found
- TruncateLine(LineBuffer, InputBuffer);
-
- if(text_parse(InputBuffer, words, &num) == 1) {
- cerr << "Parse error! Exiting..." << endl;
- cerr << endl;
- exit(0);
- }
-
- // Write the hex values in the text file to a binary file
- for(i = 0; i < num; i++) {
- if(words[i] != 0 && (strlen(words[i]) == 2)) {
- sscanf(words[i], "%x", &word_val);
- word_val &= 0xFF; // Reset the first 24 bits
- byte_val = (unsigned char) word_val;
-
- // Calculate a 32-bit CRC for each byte value
- CRC32=crc.crc32tab[(CRC32 ^ word_val)&0xFF] ^ ((CRC32>>8)&0x00ffffffL);
-
- outfile.write((unsigned char *) &byte_val, sizeof(byte_val));
- byte_count++;
- }
- }
-
- // Clear the buffers
- for(i = 0; i < MAX_LINE; i++) LineBuffer[i] = '\0';
- for(i = 0; i < MAX_LINE; i++) InputBuffer[i] = '\0';
- }
-
- // Finish 32-bit CRC calculation for each byte value
- CRC32 ^= 0xffffffffL;
-
- #ifdef __DJGPP2721__
- // DJGPP 2.7.2.1 will not create a file using ios::out|ios::in modes
- // NOTE: There is no ios::in or ios::out default mode for fstream objects.
- // Both modes must be specifed for read and write files.
- cout << "Finished." << endl;
- cout << byte_count << " bytes written to " << ofname << endl;
- cout << endl;
- infile.close();
- outfile.close();
- return; // Do not calculate CRC for output file under DJGPP
- #endif
-
- // Calculate a 32-bit CRC for the output file
- outfile_CRC32 = crc.calcCRC32(outfile);
- CRC32_check = CRC32 ^ outfile_CRC32; // XOR the CRC values
- if(CRC32_check != 0) {
- cout << "Checksum error in " << ofname << endl;
- cout << "File fails CRC-32 test." << endl;
- cout << "CRC of bytes written = ";
- cout.setf(ios::uppercase);
- cout << "0x" << setfill('0') << setw(8) << hex << CRC32 << endl;
- cout.unsetf(ios::uppercase);
- cout << "File CRC = ";
- cout.setf(ios::uppercase);
- cout << "0x" << setfill('0') << setw(8) << hex << outfile_CRC32 << endl;
- cout.unsetf(ios::uppercase);
- cout << endl;
- }
- else {
- cout << "Finished." << endl;
- cout << byte_count << " bytes written to " << ofname << endl;
- cout << endl;
- }
- infile.close();
- outfile.close();
- }
-
- void TruncateLine(char *line, char tline[MAX_LINE],
- char delimiter1, char delimiter2)
- // Used to truncate a line of text starting at the first occurrence
- // of the delimiter characters.
- {
- int len = strlen(line);
- int i, offset = 0;
-
- for(i = 0; i < len; i++) {
- if((line[i] == delimiter1) || (line[i] == delimiter2)) {
- offset = i;
- break;
- }
- }
-
- if(!offset) { // Delimiter character was not found
- tline[len] = 0; // Ensure null termination
- strcpy(tline, line);
- return;
- }
-
- len -= offset;
- tline[offset] = 0; // Ensure null termination
- memmove(tline, line, offset);
- }
-
- int text_parse(char *string, char words[MAXWORDS][MAXWORDLENGTH],
- int*numwords, char sepchar1, char sepchar2)
- // General purpose text parser. Returns 0 if successful or 1 if a
- // parse error occurred.
- {
- int i = 0;
- char newword[MAXWORDLENGTH];
- *numwords = 0;
-
- // First skip over leading blanks. Stop if an ASCII NULL is seen
- while (1) {
- if (*string == '\0') return 0;
- if (*string != ' ') break;
- string++;
- }
-
- while(1) {
- // Check to see if there is room for another word in the array
- if(*numwords == MAXWORDS) return 1;
-
- i = 0;
- while (i < MAXWORDLENGTH) {
- if(*string == 0 || *string == sepchar1 || *string == sepchar2) break;
- newword[i] = *string;
- string++;
- i++;
- }
-
- newword[i] = 0; // Ensure an ASCII null at end of newword.
- strcpy (words[*numwords], newword); // Install into array
- (*numwords)++;
-
- // If stopped by an ASCII NULL above, exit loop
- if(*string == 0) break;
-
- string++;
- if(*string == 0) break;
- }
- return 0;
- }
-
- int main(int argc, char *argv[])
- {
- // If no argument is given print usage message to the screen
- if(argc < 2) {
- HelpMessage(ProgramName, HexdumpVersionNumber);
- return 0;
- }
-
- // Process the programs command line arguments
- ProcessArgs(argc, argv);
-
- // If building a binary file from a hex dump text file,
- // execute the build function and terminate the program.
- if(building_bin_file == 1) {
- BuildBinaryFile(in_file, out_file);
- return 0;
- }
-
- if(in_file[0] == 0 ) {
- cout << endl;
- cout << "You must specify a valid input file name." << endl;
- cout << endl;
- return 0;
- }
-
- #if defined(__DOS__)
- // In MS-DOS/Windows there are two file types, text and binary
- fstream infile(in_file, ios::in | ios::binary | ios::nocreate);
- #elif defined(__DJGPP2721__)
- fstream infile(in_file, ios::in | ios::binary | ios::nocreate);
- #else
- // In UNIX there is only one file type
- fstream infile(in_file, ios::in | ios::nocreate);
- #endif
-
- if(!infile) {
- cerr << endl;
- cerr << "Cannot open file: " << in_file << endl;
- cerr << "Exiting..." << endl;
- cerr << endl;
- return 1;
- }
-
- if(display_crc32) {
- hxCRC crc;
- cout << in_file << endl;
- cout << "CRC-32 = ";
- cout.setf(ios::uppercase);
- unsigned long checksum = crc.calcCRC32(infile);
- cout << "0x" << setfill('0') << setw(8) << hex << checksum << endl;
- cout.unsetf(ios::uppercase);
- return 0;
- }
-
- if(display_crc16) {
- hxCRC crc;
- cout << in_file << endl;
- cout << "CRC-16 = ";
- cout.setf(ios::uppercase);
- unsigned short checksum = crc.calcCRC16(infile);
- cout << "0x" << setfill('0') << setw(4) << hex << checksum << endl;
- cout.unsetf(ios::uppercase);
- cout << "CCITT CRC-16 = ";
- cout.setf(ios::uppercase);
- checksum = crc.calcCRC16(infile, 0);
- cout << "0x" << setfill('0') << setw(4) << hex << checksum << endl;
- cout.unsetf(ios::uppercase);
- return 0;
- }
-
- if(out_file[0] == 0 ) { // Write output to stdout
- use_console = 1;
- if(decimal_mode == 1)
- DecFileDump(infile, cout);
- else
- HexFileDump(infile, cout);
- }
- else { // Write the output to a file
- ofstream stream(out_file, ios::out); // Open file and truncate it
- if(!stream) {
- cerr << endl;
- cerr << "Cannot create " << out_file << endl;
- cerr << endl;
- return 1;
- }
- use_console = 0;
- cerr << "Processing file..." << endl;
- if(decimal_mode == 1) {
- DecFileDump(infile, stream);
- stream.close();
- }
- else {
- HexFileDump(infile, stream);
- stream.close();
- }
- cerr << "Finished." << endl;
- }
-
- return 0;
- }
- // ----------------------------------------------------------- //
- // ------------------------------- //
- // --------- End of File --------- //
- // ------------------------------- //
-